﻿package baseEngine.utils.splitMesh
{
    import __AS3__.vec.*;
    import baseEngine.system.*;
    import baseEngine.utils.*;
    import flash.utils.*;
    import frEngine.core.*;
    import frEngine.shader.filters.*;

    public class SplitMesh extends Object
    {
        private static var vertexToTrangle:Dictionary;
        private static var boneToVertex:Dictionary;
        private static var boneToTriangle:Dictionary;
        private static var triangleToBone:Vector.<Vector.<int>>;
        private static var triangleSurface:Vector.<int>;
        private static var candidate:Vector.<TriangleEntry>;
        private static var candidateDic:Dictionary;
        private static var useBone:Vector.<int>;
        private static var boneDic:Dictionary;
        private static var triangleInCurrentSurface:Vector.<int>;
        private static var allSurfaceTriangleList:Vector.<Vector.<int>>;
        private static var allBoneUsedList:Vector.<Vector.<int>>;
        private static var addNum:int = 0;
        private static var newBoneVector:Vector.<Number>;
        private static var newIndexVector:Vector.<uint>;
        private static var splitInfo:SplitSurfaceInfo;

        public function SplitMesh()
        {
            return;
        }// end function

        private static function BuildVertexToTriangle(param1:Vector.<uint>, param2:int) : void
        {
            var _loc_3:uint = 0;
            var _loc_4:uint = 0;
            var _loc_5:uint = 0;
            trace("Indexlist长度:" + param1.length, "三角形数:" + param2);
            vertexToTrangle = new Dictionary();
            var _loc_6:int = 0;
            var _loc_7:int = 0;
            var _loc_8:int = 0;
            while (_loc_8 < param2)
            {
                
                _loc_3 = param1[_loc_8 * 3];
                _loc_4 = param1[_loc_8 * 3 + 1];
                _loc_5 = param1[_loc_8 * 3 + 2];
                if (vertexToTrangle[_loc_3] == null)
                {
                    vertexToTrangle[_loc_3] = new Array();
                }
                if (vertexToTrangle[_loc_4] == null)
                {
                    vertexToTrangle[_loc_4] = new Array();
                }
                if (vertexToTrangle[_loc_5] == null)
                {
                    vertexToTrangle[_loc_5] = new Array();
                }
                vertexToTrangle[_loc_3].push(_loc_8);
                vertexToTrangle[_loc_4].push(_loc_8);
                vertexToTrangle[_loc_5].push(_loc_8);
                _loc_8++;
            }
            return;
        }// end function

        private static function BuildBoneToVertex(param1:Vector.<Number>, param2:int) : void
        {
            var _loc_7:int = 0;
            var _loc_8:int = 0;
            var _loc_3:int = 0;
            var _loc_4:int = 0;
            boneToVertex = new Dictionary();
            var _loc_5:* = param1.length / param2;
            var _loc_6:int = 0;
            while (_loc_6 < _loc_5)
            {
                
                _loc_7 = 0;
                while (_loc_7 < param2)
                {
                    
                    _loc_8 = param1[_loc_6 * param2 + _loc_7] / 3;
                    if (boneToVertex[_loc_8] == null)
                    {
                        boneToVertex[_loc_8] = new Array();
                    }
                    boneToVertex[_loc_8].push(_loc_6);
                    _loc_7++;
                }
                _loc_6++;
            }
            return;
        }// end function

        private static function BuildBoneToTriangle() : void
        {
            var _loc_3:Object = null;
            var _loc_4:Vector.<int> = null;
            var _loc_5:Array = null;
            var _loc_6:int = 0;
            var _loc_7:int = 0;
            var _loc_8:Array = null;
            var _loc_9:int = 0;
            var _loc_10:int = 0;
            var _loc_1:int = 0;
            var _loc_2:int = 0;
            boneToTriangle = new Dictionary();
            for (_loc_3 in boneToVertex)
            {
                
                _loc_4 = new Vector.<int>;
                _loc_5 = boneToVertex[_loc_3];
                _loc_6 = _loc_5.length;
                _loc_7 = 0;
                while (_loc_7 < _loc_6)
                {
                    
                    _loc_8 = vertexToTrangle[_loc_5[_loc_7]];
                    _loc_9 = _loc_8.length;
                    _loc_10 = 0;
                    while (_loc_10 < _loc_9)
                    {
                        
                        if (_loc_4.indexOf(_loc_8[_loc_10]) == -1)
                        {
                            _loc_4.push(_loc_8[_loc_10]);
                        }
                        _loc_10++;
                    }
                    _loc_7++;
                }
                boneToTriangle[_loc_3] = _loc_4;
            }
            return;
        }// end function

        private static function BuildTriangleToBone(param1:Vector.<uint>, param2:int, param3:Vector.<Number>, param4:int) : void
        {
            var _loc_7:int = 0;
            var _loc_8:int = 0;
            var _loc_9:int = 0;
            var _loc_11:int = 0;
            var _loc_12:int = 0;
            var _loc_13:int = 0;
            var _loc_14:int = 0;
            var _loc_5:int = 0;
            var _loc_6:int = 0;
            triangleToBone = new Vector.<Vector.<int>>(param2);
            var _loc_10:int = 0;
            while (_loc_10 < param2)
            {
                
                triangleToBone[_loc_10] = new Vector.<int>;
                _loc_7 = param1[_loc_10 * 3];
                _loc_8 = param1[_loc_10 * 3 + 1];
                _loc_9 = param1[_loc_10 * 3 + 2];
                _loc_11 = 0;
                while (_loc_11 < param4)
                {
                    
                    _loc_12 = param3[_loc_7 * param4 + _loc_11] / 3;
                    _loc_13 = param3[_loc_8 * param4 + _loc_11] / 3;
                    _loc_14 = param3[_loc_9 * param4 + _loc_11] / 3;
                    if (triangleToBone[_loc_10].indexOf(_loc_12) == -1)
                    {
                        triangleToBone[_loc_10].push(_loc_12);
                    }
                    if (triangleToBone[_loc_10].indexOf(_loc_13) == -1)
                    {
                        triangleToBone[_loc_10].push(_loc_13);
                    }
                    if (triangleToBone[_loc_10].indexOf(_loc_14) == -1)
                    {
                        triangleToBone[_loc_10].push(_loc_14);
                    }
                    _loc_11++;
                }
                _loc_10++;
            }
            return;
        }// end function

        private static function addTriangleToCandidates(param1:int) : void
        {
            var _loc_6:int = 0;
            if (triangleSurface[param1] >= 0)
            {
                return;
            }
            var _loc_2:* = new TriangleEntry();
            _loc_2.index = param1;
            _loc_2.boneToAdd = 0;
            var _loc_3:* = triangleToBone[param1];
            var _loc_4:int = 0;
            while (_loc_4 < _loc_3.length)
            {
                
                _loc_6 = _loc_3[_loc_4];
                if (boneDic[_loc_6] == null)
                {
                    var _loc_7:* = _loc_2;
                    var _loc_8:* = _loc_2.boneToAdd + 1;
                    _loc_7.boneToAdd = _loc_8;
                }
                _loc_4++;
            }
            var _loc_5:* = candidate.length;
            candidate.push(_loc_2);
            candidateDic[param1] = candidate[_loc_5];
            triangleSurface[param1] = 0;
            return;
        }// end function

        private static function addBoneToUse(param1:int) : void
        {
            var _loc_4:int = 0;
            var _loc_5:TriangleEntry = null;
            if (boneDic[param1] != null)
            {
                return;
            }
            boneDic[param1] = useBone.length;
            useBone.push(param1);
            var _loc_2:* = boneToTriangle[param1];
            var _loc_3:int = 0;
            while (_loc_3 < _loc_2.length)
            {
                
                _loc_4 = _loc_2[_loc_3];
                if (candidateDic[_loc_4] != null)
                {
                    _loc_5 = candidateDic[_loc_4];
                    var _loc_6:* = _loc_5;
                    var _loc_7:* = _loc_5.boneToAdd - 1;
                    _loc_6.boneToAdd = _loc_7;
                }
                else
                {
                    addTriangleToCandidates(_loc_4);
                }
                _loc_3++;
            }
            return;
        }// end function

        private static function addTriangleToSurface(param1:int, param2:int) : void
        {
            if (triangleSurface[param1] > 0)
            {
                trace("Error 已被添加的点");
                return;
            }
            if (param2 <= 0)
            {
                trace("Error sur_id");
                return;
            }
            if (triangleSurface[param1] == 0)
            {
            }
            triangleSurface[param1] = param2;
            triangleInCurrentSurface.push(param1);
            var _loc_3:* = triangleToBone[param1];
            var _loc_4:int = 0;
            while (_loc_4 < _loc_3.length)
            {
                
                addBoneToUse(_loc_3[_loc_4]);
                _loc_4++;
            }
            return;
        }// end function

        private static function addTriangleWithoutBoneToSurface(param1:int, param2:int) : void
        {
            if (triangleSurface[param1] > 0)
            {
                trace("Error 已被添加的点");
                return;
            }
            if (param2 <= 0)
            {
                trace("Error sur_id");
                return;
            }
            triangleSurface[param1] = param2;
            triangleInCurrentSurface.push(param1);
            return;
        }// end function

        private static function compare(param1:TriangleEntry, param2:TriangleEntry) : Number
        {
            if (param1.boneToAdd > param2.boneToAdd)
            {
                return -1;
            }
            if (param1.boneToAdd == param2.boneToAdd)
            {
                if (param1.index > param2.index)
                {
                    return -1;
                }
                return 1;
            }
            return 1;
        }// end function

        private static function getNextTriangleNotInSurface() : int
        {
            var _loc_1:* = triangleSurface.length;
            var _loc_2:int = 0;
            while (_loc_2 < _loc_1)
            {
                
                if (triangleSurface[_loc_2] == -1)
                {
                    return _loc_2;
                }
                _loc_2++;
            }
            return -1;
        }// end function

        private static function splitOneSurface(param1:int, param2:int) : void
        {
            var _loc_5:TriangleEntry = null;
            var _loc_6:int = 0;
            candidate = new Vector.<TriangleEntry>;
            candidateDic = new Dictionary();
            useBone = new Vector.<int>;
            boneDic = new Dictionary();
            triangleInCurrentSurface = new Vector.<int>;
            var _loc_3:* = Device3D.maxBonesPerSurface;
            addTriangleToSurface(param2, param1);
            while (true)
            {
                
                candidate.sort(compare);
                while (candidate.length != 0 && candidate[(candidate.length - 1)].boneToAdd == 0)
                {
                    
                    _loc_5 = candidate[(candidate.length - 1)];
                    candidateDic[_loc_5.index] = null;
                    candidate.pop();
                    addTriangleWithoutBoneToSurface(_loc_5.index, param1);
                }
                if (candidate.length == 0)
                {
                    _loc_6 = getNextTriangleNotInSurface();
                    if (_loc_6 == -1)
                    {
                        break;
                    }
                    addTriangleToCandidates(_loc_6);
                    _loc_5 = candidateDic[_loc_6];
                }
                else
                {
                    _loc_5 = candidate[(candidate.length - 1)];
                }
                if (_loc_5.boneToAdd + useBone.length > _loc_3)
                {
                    break;
                    continue;
                }
                candidateDic[_loc_5.index] = null;
                candidate.pop();
                addTriangleToSurface(_loc_5.index, param1);
            }
            var _loc_4:int = 0;
            while (_loc_4 < candidate.length)
            {
                
                triangleSurface[candidate[_loc_4].index] = -1;
                _loc_4++;
            }
            return;
        }// end function

        private static function mainSplit(param1:Vector.<uint>, param2:int, param3:Vector.<Number>, param4:int) : void
        {
            triangleSurface = new Vector.<int>(param2);
            var _loc_5:int = 0;
            while (_loc_5 < param2)
            {
                
                triangleSurface[_loc_5] = -1;
                _loc_5++;
            }
            allSurfaceTriangleList = new Vector.<Vector.<int>>;
            allBoneUsedList = new Vector.<Vector.<int>>;
            var _loc_6:int = 1;
            var _loc_7:* = getNextTriangleNotInSurface();
            while (_loc_7 != -1)
            {
                
                splitOneSurface(_loc_6, _loc_7);
                allSurfaceTriangleList.push(triangleInCurrentSurface);
                allBoneUsedList.push(useBone);
                trace("分割出surface:" + _loc_6, "三角形数量:" + triangleInCurrentSurface.length, "骨头数量:" + useBone.length);
                _loc_6++;
                _loc_7 = getNextTriangleNotInSurface();
            }
            trace("分割完成！");
            return;
        }// end function

        private static function addVertex(param1:int, param2:int, param3:Dictionary) : void
        {
            var _loc_4:Object = null;
            var _loc_5:int = 0;
            var _loc_6:int = 0;
            var _loc_7:Vector.<Number> = null;
            var _loc_9:* = addNum + 1;
            addNum = _loc_9;
            for (_loc_4 in param3)
            {
                
                _loc_5 = 0;
                _loc_6 = _loc_4.sizePerVertex;
                _loc_7 = _loc_4.vertexVector;
                if (_loc_7.length < (param2 + 1) * _loc_6)
                {
                    _loc_7.length = (param2 + 1) * _loc_6;
                }
                while (_loc_5 < _loc_6)
                {
                    
                    _loc_7[param2 * _loc_6 + _loc_5] = _loc_7[param1 * _loc_6 + _loc_5];
                    _loc_5++;
                }
            }
            return;
        }// end function

        private static function rebuildVector(param1:Vector.<uint>, param2:int, param3:Vector.<Number>, param4:int, param5:Dictionary) : void
        {
            var _loc_14:int = 0;
            var _loc_15:int = 0;
            var _loc_16:int = 0;
            var _loc_18:int = 0;
            var _loc_19:Vector.<int> = null;
            var _loc_20:int = 0;
            var _loc_21:int = 0;
            var _loc_22:int = 0;
            var _loc_23:int = 0;
            var _loc_24:int = 0;
            var _loc_25:int = 0;
            var _loc_26:int = 0;
            var _loc_27:int = 0;
            var _loc_28:int = 0;
            var _loc_29:Vector.<int> = null;
            newBoneVector = new Vector.<Number>(param3.length);
            newIndexVector = new Vector.<uint>(param1.length);
            splitInfo = new SplitSurfaceInfo();
            splitInfo.skinData = allBoneUsedList;
            var _loc_6:* = splitInfo.startIndex;
            var _loc_7:* = splitInfo.triangleNum;
            addNum = 0;
            var _loc_8:* = param3.length / param4;
            var _loc_9:* = int(_loc_8 * 3);
            var _loc_10:* = new Vector.<uint>(_loc_9);
            var _loc_11:* = new Vector.<uint>(_loc_9);
            var _loc_12:int = 0;
            var _loc_13:* = allSurfaceTriangleList.length;
            var _loc_17:int = 0;
            while (_loc_17 < _loc_13)
            {
                
                _loc_18 = _loc_17 + 1;
                _loc_6.push(_loc_12);
                _loc_19 = allSurfaceTriangleList[_loc_17];
                _loc_7.push(_loc_19.length);
                _loc_20 = 0;
                while (_loc_20 < _loc_19.length)
                {
                    
                    _loc_21 = _loc_19[_loc_20];
                    _loc_22 = param1[_loc_21 * 3];
                    _loc_23 = param1[_loc_21 * 3 + 1];
                    _loc_24 = param1[_loc_21 * 3 + 2];
                    if (_loc_10[_loc_22] == 0)
                    {
                        _loc_10[_loc_22] = _loc_18;
                        var _loc_30:* = _loc_22;
                        _loc_11[_loc_22] = _loc_22;
                        _loc_14 = _loc_30;
                    }
                    else if (_loc_10[_loc_22] != _loc_18)
                    {
                        addVertex(_loc_22, _loc_8, param5);
                        var _loc_30:* = _loc_8;
                        _loc_11[_loc_22] = _loc_8;
                        _loc_14 = _loc_30;
                        _loc_10[_loc_22] = _loc_18;
                        newBoneVector.length = newBoneVector.length + param4;
                        _loc_8++;
                    }
                    else
                    {
                        _loc_14 = _loc_11[_loc_22];
                    }
                    if (_loc_10[_loc_23] == 0)
                    {
                        _loc_10[_loc_23] = _loc_18;
                        var _loc_30:* = _loc_23;
                        _loc_11[_loc_23] = _loc_23;
                        _loc_15 = _loc_30;
                    }
                    else if (_loc_10[_loc_23] != _loc_18)
                    {
                        addVertex(_loc_23, _loc_8, param5);
                        var _loc_30:* = _loc_8;
                        _loc_11[_loc_23] = _loc_8;
                        _loc_15 = _loc_30;
                        _loc_10[_loc_23] = _loc_18;
                        newBoneVector.length = newBoneVector.length + param4;
                        _loc_8++;
                    }
                    else
                    {
                        _loc_15 = _loc_11[_loc_23];
                    }
                    if (_loc_10[_loc_24] == 0)
                    {
                        _loc_10[_loc_24] = _loc_18;
                        var _loc_30:* = _loc_24;
                        _loc_11[_loc_24] = _loc_24;
                        _loc_16 = _loc_30;
                    }
                    else if (_loc_10[_loc_24] != _loc_18)
                    {
                        addVertex(_loc_24, _loc_8, param5);
                        var _loc_30:* = _loc_8;
                        _loc_11[_loc_24] = _loc_8;
                        _loc_16 = _loc_30;
                        _loc_10[_loc_24] = _loc_18;
                        newBoneVector.length = newBoneVector.length + param4;
                        _loc_8++;
                    }
                    else
                    {
                        _loc_16 = _loc_11[_loc_24];
                    }
                    newIndexVector[_loc_12] = _loc_14;
                    newIndexVector[(_loc_12 + 1)] = _loc_15;
                    newIndexVector[_loc_12 + 2] = _loc_16;
                    _loc_12 = _loc_12 + 3;
                    _loc_25 = 0;
                    while (_loc_25 < param4)
                    {
                        
                        _loc_26 = param3[_loc_22 * param4 + _loc_25] / 3;
                        _loc_27 = param3[_loc_23 * param4 + _loc_25] / 3;
                        _loc_28 = param3[_loc_24 * param4 + _loc_25] / 3;
                        _loc_29 = allBoneUsedList[_loc_17];
                        newBoneVector[_loc_14 * param4 + _loc_25] = _loc_29.indexOf(_loc_26) * 3;
                        newBoneVector[_loc_15 * param4 + _loc_25] = _loc_29.indexOf(_loc_27) * 3;
                        newBoneVector[_loc_16 * param4 + _loc_25] = _loc_29.indexOf(_loc_28) * 3;
                        _loc_25++;
                    }
                    _loc_20++;
                }
                _loc_17++;
            }
            return;
        }// end function

        public static function split(param1:FrSurface3D) : SplitSurfaceInfo
        {
            var _loc_2:* = param1.getVertexBufferByNameId(FilterName_ID.SKIN_INDICES_ID);
            param1.indexBufferFr.numTriangles = param1.indexVector.length / 3;
            var _loc_3:* = _loc_2.vertexVector;
            var _loc_4:* = param1.indexVector;
            var _loc_5:* = _loc_2.sizePerVertex;
            var _loc_6:* = param1.getUseSameBufferVoList();
            SplitMesh.BuildVertexToTriangle(_loc_4, param1.indexBufferFr.numTriangles);
            SplitMesh.BuildBoneToVertex(_loc_3, _loc_5);
            SplitMesh.BuildBoneToTriangle();
            SplitMesh.BuildTriangleToBone(_loc_4, param1.indexBufferFr.numTriangles, _loc_3, _loc_5);
            SplitMesh.mainSplit(_loc_4, param1.indexBufferFr.numTriangles, _loc_3, _loc_5);
            SplitMesh.rebuildVector(_loc_4, param1.indexBufferFr.numTriangles, _loc_3, _loc_5, _loc_6);
            _loc_2.vertexVector = newBoneVector;
            param1.indexVector = newIndexVector;
            trace("顶点数：" + (newBoneVector.length / _loc_5 - addNum), "新增顶点数：" + addNum, "surfaceNum:" + splitInfo.skinData.length);
            return splitInfo;
        }// end function

    }
}
